﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;
using Bamboo.Helpers;

namespace VietThinks.Website
{
    public partial class VisitContext
    {
        public class CookieManager
        {
            private CookieManager() { }

            private static readonly CookieManager instance = new CookieManager();

            public static CookieManager Instance
            {
                get { return instance; }
            }

            public static HttpCookie GetCookieValue(string key)
            {
                if (HttpContext.Current.Request.Cookies[key] == null)
                {
                    return null;
                }

                return HttpContext.Current.Request.Cookies[key];
            }

            public static void SetCookieValue(string key, string value, DateTime? expiresWhen)
            {
                var cookie = new HttpCookie(key, value);

                if (expiresWhen.HasValue)
                {
                    cookie.Expires = expiresWhen.Value;
                };

                HttpContext.Current.Response.Cookies.Set(cookie);
            }

            private static void SetCookieValue(string key, string value, TimeSpan timeToLive)
            {
                SetCookieValue(key, value, DateTime.Now.Add(timeToLive));
            }

            private void SetCookieValue(string key, string value)
            {
                SetCookieValue(key, value, this.GetCookieTimeoutSetting(key));
            }

            private TimeSpan GetCookieTimeoutSetting(string propertyName)
            {
                var property = TypeDescriptor.GetProperties(this)
                                   .Cast<PropertyDescriptor>()
                                   .Where(p => p.Name == propertyName).SingleOrDefault();

                if (property != null)
                {
                    var expiration = property.Attributes.OfType<ExpireAttribute>().FirstOrDefault();

                    if (expiration != null)
                    {
                        return expiration.Timeout;
                    }
                }

                return TimeSpan.Zero;
            }

            public string SessionIdByCookie
            {
                get
                {
                    var sessionId = GetCookieValue("ASP.NET_SessionId");

                    return sessionId == null ? string.Empty : sessionId.Value;
                }
            }

            [Expire("GuestCookieTimeoutInDays")]
            public int? GuestId
            {
                get
                {
                    int guestId;

                    var cookie = GetCookieValue("GuestId");

                    if (cookie == null || !Int32.TryParse(cookie.Value, out guestId))
                    {
                        return null;
                    }

                    return guestId;
                }
                set
                {
                    this.SetCookieValue("GuestId", value.ToStringEx());
                }
            }

            [Expire("GuestCookieTimeoutInDays")]
            public string GuestShippingQuoteZipCode
            {
                get
                {
                    var zipCode = GetCookieValue("GuestShippingQuoteZipCode");
                    return zipCode == null ? string.Empty : zipCode.Value;
                }
                set
                {
                    SetCookieValue("GuestShippingQuoteZipCode", value);
                }
            }

            //// Cookie will expire at the end of session
            //public string OmnitureTransactionId
            //{
            //    get 
            //    {
            //        var transactionId = GetCookieValue("OmnitureTransactionId");
            //        return transactionId == null ? null : transactionId.Value;
            //    }
            //    set 
            //    { 
            //        SetCookieValue("OmnitureTransactionId", value, null);
            //    }
            //}

            //// Cookie will expire at the end of session
            //public string OmnitureSessionId
            //{
            //    get 
            //    { 
            //        var sessionId = GetCookieValue("OmnitureSessionId");
            //        return sessionId == null ? null: sessionId.Value; 
            //    }
            //    set 
            //    {
            //        // Cookie will expire at the end of session
            //        SetCookieValue("OmnitureSessionId", value, null);
            //    }
            //}

            // Cookie will expire at the end of session
            //public string BreadCrumb
            //{
            //    get
            //    {
            //        var sessionId = GetCookieValue("BreadCrumb");
            //        return sessionId == null ? null : sessionId.Value;
            //    }
            //    set
            //    {
            //        // Cookie will expire at the end of session
            //        SetCookieValue("BreadCrumb", value, null);
            //    }
            //}

        }

        [AttributeUsage(AttributeTargets.Property)]
        internal class ExpireAttribute : Attribute
        {
            public ExpireAttribute(TimeSpan timeout)
            {
                this.Timeout = timeout;
            }

            public ExpireAttribute(string appSettingKey)
            {
                var reader = new System.Configuration.AppSettingsReader();

                object value = reader.GetValue(appSettingKey, typeof(int));

                if (value == null)
                {
                    throw new ArgumentException("AppSetting {0} could not be found.", appSettingKey);
                }

                var timeoutInDays = (int)value;

                this.Timeout = TimeSpan.FromDays(timeoutInDays);
            }

            public TimeSpan Timeout { get; private set; }
        }
    }
}